package tako.wisers.com.android.apis.location;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import tako.wisers.com.android.apis.R;
import tako.wisers.com.android.apis.http.HttpGeter;
import tako.wisers.com.android.apis.location.overlay.RouteOverlay;
import tako.wisers.com.android.apis.util.Configration;
import tako.wisers.com.android.apis.util.Global;

import android.app.Activity;
import android.graphics.Color;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class RouteDrawer {
	private GeoPoint mStartPoint;
	private GeoPoint mEndPoint;
	private static final String URL = Configration.getInstance().getProperty(
			Global.ROUTE_SERVICE_KEY);
	private MapView mMapView;
	private OverlayControl mOverlayControl;
	private Double mSumDistance;
	private int mRouteMode;

	public RouteDrawer(Activity activity, GeoPoint startPoint, GeoPoint endPoint, MapView mapView) {
		mStartPoint = startPoint;
		mEndPoint = endPoint;
		mMapView = mapView;
		mRouteMode = activity.getIntent().getIntExtra(Global.ROUTE_MODE, R.id.drive_route);
		mOverlayControl = new OverlayControl(mapView);
		mOverlayControl.build(activity);
	}

	public boolean draw() {
		try {
			InputStream kmlInput = getKMLInputStream();
			parser(kmlInput);
			IOUtils.closeQuietly(kmlInput);
			return true;
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}

	private InputStream getKMLInputStream() {
		String startLac = int2double(mStartPoint.getLatitudeE6()) + ","
				+ int2double(mStartPoint.getLongitudeE6());
		String endLac = int2double(mEndPoint.getLatitudeE6()) + ","
				+ int2double(mEndPoint.getLongitudeE6());
		String url = null;
		switch (mRouteMode) {
		case R.id.walk_route:
			url = String.format(URL, startLac, endLac, Global.WALK_MODE, Global.WALK_FLAG);
			break;
		default:
			url = String.format(URL, startLac, endLac, Global.DRIVE_MODE, Global.DRIVE_FLAG);
		}
		
		HttpGeter geter = new HttpGeter(url);
		return geter.getInputStream();
	}

	private void parser(InputStream is) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(is);
		RouteDistanceCount disCount = new RouteDistanceCount();

		if (doc.getElementsByTagName("GeometryCollection").getLength() > 0) {
			// String path =
			// doc.getElementsByTagName("GeometryCollection").item(0).getFirstChild().getFirstChild().getNodeName();
			String path = doc.getElementsByTagName("GeometryCollection")
					.item(0).getFirstChild().getFirstChild().getFirstChild()
					.getNodeValue();
			String[] pairs = path.split(" ");
			String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude
													// lngLat[1]=latitude
													// lngLat[2]=height
			GeoPoint startGP = new GeoPoint((int) (Double
					.parseDouble(lngLat[1]) * 1E6), (int) (Double
					.parseDouble(lngLat[0]) * 1E6));
			disCount.setPointOfRoute(mStartPoint, startGP);
			mOverlayControl.setOverlay(startGP);
			GeoPoint gp1;
			GeoPoint gp2 = startGP;
			RouteOverlay showTextPoint = null;
			for (int i = 1; i < pairs.length; i++) // the last one would be crash
			{
				lngLat = pairs[i].split(",");
				gp1 = gp2;
				// watch out! For GeoPoint, first:latitude, second:longitude
				gp2 = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6),
						(int) (Double.parseDouble(lngLat[0]) * 1E6));
				RouteOverlay overlay = new RouteOverlay(gp1, gp2, 2, Color.BLUE);
				if(i > pairs.length / 2 && showTextPoint == null){
					showTextPoint = overlay;
				} 
				mMapView.getOverlays().add(overlay);
				disCount.setPointOfRoute(gp1, gp2);
			}
			disCount.setPointOfRoute(gp2, mEndPoint);
			mOverlayControl.setOverlay(mEndPoint);
			mSumDistance = disCount.getDistance();
			String distanceText = mRouteMode == R.id.walk_route ? "Walk distance:" : "Drive distance:";
			if(showTextPoint != null) showTextPoint.setText(distanceText + mSumDistance.toString() + "km");
			System.gc();
		}

	}

	private double int2double(int loc) {
		return (double) loc / Global.MILLION;
	}
}
